#!/usr/bin/env python
# -*- coding: utf-8 -*-

import argparse
import os
import sys
import signal

from .dispatcher import CMDDispatcher
from .dispatcher import CMDCommonOptionDispatcher
from .utils.log import logger
from .utils.configure import AppConfig
from .utils.process import kill_process_tree, get_children_processes


def _set_signal_handler():
    def terminal_all(signal, frame):
        logger.info("Terminate all sub processes")
        os.sync()
        children = get_children_processes(os.getpid())
        for pid in children:
            print("Kill {}...".format(pid))
            kill_process_tree(pid)

    signal.signal(signal.SIGTERM, terminal_all)
    signal.signal(signal.SIGINT, terminal_all)
    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
    signal.signal(signal.SIGXFSZ, signal.SIG_DFL)
    


def _setup_env(config):
    run_path_list = [
        'test_cache_path',
        'test_run_path',
        'test_result_path',
    ]
    for p in run_path_list:
        if config.get(p):
            if not os.path.exists(config[p]):
                try:
                    os.makedirs(config[p])
                except BaseException as e:
                    print("Create directory failed: {}".format(config[p]))
                    raise(e)


def run():
    """Entry point of tone"""
    # Set Signal Handler
    _set_signal_handler()
    # tone must run as root
    if os.geteuid() != 0:
        logger.error("Please run tone via root!")
        return False
    # Add tone path to sys.path
    basedir = os.path.dirname(os.path.realpath(__file__))
    if basedir not in sys.path:
        sys.path.append(basedir)

    # CLI parser
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(help="Sub Commands Help")
    # todo: add version rule
    parser.add_argument("-v", "--version", action="version", version="0.1")

    # Config
    # todo: read the config files
    config = AppConfig()
    config.tone_path = os.path.dirname(basedir)
    configfile = os.path.join(config.tone_path, "etc", "config.yaml")
    config.load_from_yaml(configfile)
    config.load_from_env()
    config.bash_lib_path = os.path.join(config.tone_path, "lib")

    cmd_dispatch = CMDDispatcher()
    cmd_dispatch.map_method("configure", subparsers)
    cmd_common_dispath = CMDCommonOptionDispatcher()
    cmd_common_dispath.map_method("configure", subparsers)

    args = parser.parse_args()
    # todo: merge args
    config.parser = vars(args)
    cmd_common_dispath.map_method("run", config)
    # setup test env
    _setup_env(config)

    # Run Logic
    subcmd = config.parser['subcommand'] if config.parser else ""
    config.subcommand = subcmd
    try:
        if subcmd in ('fetch', 'install', 'uninstall', 'archive'):
            worker = cmd_dispatch['subcommand']
        else:
            worker = cmd_dispatch[subcmd]
        logger.debug(worker)
        return worker.obj.run(config)
    except KeyError:
        parser.print_help()
    finally:
        logger.debug("complete!")


if __name__ == "__main__":
    run()
